package io.ouka.jvm.hotspot.selfread.read;

import io.ouka.jvm.hotspot.selfread.InstanceKlass;
import io.ouka.jvm.hotspot.selfread.constant.FinalConstant;
import io.ouka.jvm.hotspot.selfread.domain.AttributeInfo;
import io.ouka.jvm.hotspot.selfread.domain.MethodInfo;
import io.ouka.jvm.hotspot.selfread.util.DataTranslate;

/**
 * @author ouka
 * AttributeReader
 */
public class AttributeReader extends AbstractReader {
    private int attributeNum;
    private int attributeReadIndex = 0;

    @Override
    public void preRead(byte[] content) {
        System.arraycopy(content, index, FinalConstant.U2BYTE, 0, FinalConstant.u2);
        this.attributeNum = DataTranslate.byteToUnsignedShort(FinalConstant.U2BYTE);
        index += FinalConstant.u2;
        byte[] bytes = new byte[content.length - index];
        System.arraycopy(content, index, bytes, 0, content.length - index);
        this.selfContent = bytes;
    }

    @Override
    public void read() {
        for (int i = 0; i < attributeNum; i++) {
            System.arraycopy(selfContent, attributeReadIndex, FinalConstant.U2BYTE, 0, FinalConstant.u2);
            index += FinalConstant.u2;
            attributeReadIndex += FinalConstant.u2;
            int attributeIndex = DataTranslate.byteToUnsignedShort(FinalConstant.U2BYTE);
            AttributeInfo attributeInfo = new AttributeInfo();
            attributeInfo.setAttributeNameIndex(attributeIndex);
            String type = (String) instanceKlass.getConstantPool().getDataMap().get(attributeIndex);
            if (type.equals("SourceFile")) {
                parseSourceFile(attributeInfo);
            } else {
                throw new IllegalArgumentException("unKnow type");
            }
        }
        for (MethodInfo method : instanceKlass.getMethods()) {
            method.setInstanceKlass(instanceKlass);
        }
    }

    private void parseSourceFile(AttributeInfo attributeInfo) {
        System.arraycopy(selfContent, attributeReadIndex, FinalConstant.U4BYTE, 0, FinalConstant.u4);
        attributeReadIndex += FinalConstant.u4;
        index += FinalConstant.u4;
        int length = DataTranslate.byteArrayToInt(FinalConstant.U4BYTE);
        attributeInfo.setAttributeLength(length);
        byte[] bytes = new byte[length];
        System.arraycopy(selfContent, attributeReadIndex, bytes, 0, length);
        attributeInfo.setInfo(bytes);
    }
}
